# GetUserSignInDataGraph.PS1
# A script to fetch user sign-in data from the Microsoft Graph
# https://github.com/12Knocksinna/Office365itpros/blob/master/GetUserSignInDataGraphSDK.PS1
#
Clear-Host


# Get User sign in data
Write-Host "Accessing the Graph to get user sign-in data..."
$URI = "https://graph.microsoft.com/beta/users?`$select=displayName,userPrincipalName, mail, id, CreatedDateTime, signInActivity, UserType&`$top=100"
[array]$SignInData = (Invoke-RestMethod -Uri $URI -Headers $Headers -Method Get -ContentType "application/json") 
If ($SignInData.Value.count) {
    $SignInData = $SignInData.Value
}
$Report = [System.Collections.Generic.List[Object]]::new() 

ForEach ($User in $SignInData) {  
   [string]$LastSignInOutput = $Null
   If ($Null -ne $User.SignInActivity)     {
      $LastUserSignInDate = $User.SignInActivity['lastSignInDateTime']
      If ($Null -ne $LastUserSignInDate) {
          $LastSignInOutput = Get-Date($LastUserSignInDate) -format g
          $DaysSinceSignIn = (New-TimeSpan $LastUserSignInDate).Days
      }
   } Else { #No sign in data for this user account
      $LastSignInOutput = "Never or > 180 days" 
      $DaysSinceSignIn = "N/A" 
   }
 
   $ReportLine  = [PSCustomObject] @{          
     UPN                = $User.UserPrincipalName
     DisplayName        = $User.DisplayName
     Email              = $User.Mail
     ObjectId           = $User.Id
     Created            = Get-Date($User.CreatedDateTime) -format g      
     LastSignIn         = $LastSignInOutput
     DaysSinceSignIn    = $DaysSinceSignIn
     UserType           = $User.UserType }
   $Report.Add($ReportLine) 
} # End ForEach

# Do we have extra data to fetch?
$NextLink = $SignInData.'@Odata.NextLink'

While ($Null -ne $NextLink) { # We do... so process them.
   Write-Host "Still processing..."
   $SignInData = Invoke-WebRequest -Method GET -Uri $NextLink -ContentType "application/json" -Headers $Headers
   $SignInData = $SignInData | ConvertFrom-JSon
   ForEach ($User in $SignInData.Value) {  
      [string]$LastSignInOutput = $Null
      If ($Null -ne $User.SignInActivity)     {
         $LastUserSignInDate = $User.SignInActivity.LastSignInDateTime
         If ($Null -ne $LastUserSignInDate) {
            $LastSignInOutput = Get-Date($LastUserSignInDate) -format g
            $DaysSinceSignIn = (New-TimeSpan $LastUserSignInDate).Days
        }
      } Else { #No sign in data for this user account
         $LastSignInOutput = "Never or > 180 days" 
         $DaysSinceSignIn = "N/A" 
      }
     
   $ReportLine  = [PSCustomObject] @{  
     UPN                = $User.UserPrincipalName
     DisplayName        = $User.DisplayName
     Email              = $User.Mail
     ObjectId           = $User.Id
     Created            = Get-Date($User.CreatedDateTime) -format g      
     LastSignIn         = $LastSignInOutput
     DaysSinceSignIn    = $DaysSinceSignIn
     UserType           = $User.UserType        }
     $Report.Add($ReportLine) } 

   # Check for more data
   $NextLink = $SignInData.'@Odata.NextLink'
} # End While

Write-Host "All done. " $Report.Count "accounts processed - output available in c:\Temp\ReportUserSignin.csv."
$Report | Sort-Object DisplayName | Out-GridView
$Report | Export-CSV -NoTypeInformation c:\Temp\ReportUserSignin.csv

# An example script used to illustrate a concept. More information about the topic can be found in the Office 365 for IT Pros eBook https://gum.co/O365IT/
# and/or a relevant article on https://office365itpros.com or https://www.practical365.com. See our post about the Office 365 for IT Pros repository # https://office365itpros.com/office-365-github-repository/ for information about the scripts we write.

# Do not use our scripts in production until you are satisfied that the code meets the need of your organization. Never run any code downloaded from the Internet without
# first validating the code in a non-production environment.
